<?php

namespace app\zyhsapi\model;

use app\common\cachemodel\zlcr3\Zlcr3ConsultAccount;
use app\common\lib\exception\ApiException;
use app\common\lib\Util;
use app\zyhsapi\service\CacheZyhs;
use think\Log;
use traits\model\SoftDelete;
use XznsTools\cache\zyhs\CacheManageZyhs;

class ZyhsUserQuestion extends BaseCacheZyhs
{
    protected $table = 'good_wechat.zyhs_user_question';

    protected $cacheModel = 'question_answer.question';

    use SoftDelete;

    /**
     * 根据问题的类型，返回文字和语音的最大最小输入配置
     * @param $question_type 1：星盘；2：骰子；3：塔罗；
     * @return int[]|void
     */
    public function answerRule($question_type)
    {
        $questionGoods = config('zyhs_question.info');

        switch ($question_type)
        {
            case 1:
                return [  // 星盘
                    'text_min' => $questionGoods[10000]['text_min'] ?? 240,
                    'text_max' => $questionGoods[10000]['text_max'] ?? 400,
                    'duration_min' => Util::isOnline() ? $questionGoods[10000]['duration_min'] : 12,
                    'duration_max' => $questionGoods[10000]['duration_max'] ?? 300,
                ];
            case 2:
                return [  // 骰子
                    'text_min' => $questionGoods[10006]['text_min'] ?? 50,
                    'text_max' => $questionGoods[10006]['text_max'] ?? 240,
                    'duration_min' => Util::isOnline() ? $questionGoods[10006]['duration_min'] : 6,
                    'duration_max' => $questionGoods[10006]['duration_max'] ?? 300,
                ];
            case 3:
                return [  // 塔罗
                    'text_min' => $questionGoods[10003]['text_min'] ?? 180,
                    'text_max' => $questionGoods[10003]['text_max'] ?? 300,
                    'duration_min' => Util::isOnline() ? $questionGoods[10003]['duration_min'] : 12,
                    'duration_max' => $questionGoods[10003]['duration_max'] ?? 300,
                ];
        }
    }

    /**
     * 新增问答信息
     */
    public function SaveData($uid, $data)
    {
        try
        {
            $nowTime = time();
//            $data = [
//                'uid' => $uid,
//                'question' => '', // 咨询问题
//                'question_type' => 1, // 1=>星盘 2=>骰子 3=>塔罗
//                'gid' => 0,   // 商品ID
//                'question_extend' => '',  // 星盘悬赏的档案信息|塔罗结果|骰子结果
//                'is_synastry' => 0,   // 是否是合盘
//                'order_num' => '',    // 订单编号
//                'consult_num' => '',  // 咨询人数
//                'good_amount' => ''   // 实际支付价格（准币）
//            ];
            $data['id'] = Util::ZyhsCreateQuestionAnswerId();
            $data['status'] = 1;
            $data['is_hide'] = 0;
            $data['is_read'] = 1;
            $data['create_time'] = $nowTime;
            $data['pay_time'] = $nowTime;

            $this->insert($data);
            // 问题添加至我的问答-提问列表
            $this->listDataAdd($uid, [$data['id'] => $data['id']]);
            return $data['id'];
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return '';
        }
    }

    /**
     * 更新问答信息
     */
    public function UpdateData($qid, $data)
    {
        try
        {
            $uid = $data['uid'] ?? 0;
            if (isset($data['extend']))
            {
                $data['extend'] = json_encode($data['extend'], JSON_UNESCAPED_UNICODE);
            }
            unset($data['uid']);
            $this::withTrashed()->where(['id' => (string)$qid])->update($data);

            if (isset($data['first_reply_time']) && $data['first_reply_time'])
            {   // 添加至时间排序列表
                CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->listAdd([$qid => $data['first_reply_time']], 0, 'time_sort');
            }

            if (isset($data['is_read']))
            {
                if ($data['is_read'] === 1)
                {
                    CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('unread_question', $uid)->delJudge($qid, 'unread_question');
                } else
                {
                    CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('unread_question', $uid)->listAdd([$qid => $qid], 0, 'unread_question');
                }
            }
            // 我的问答列表缓存
            if (isset($data['delete_time']))
            {
                $this->listDataDel($uid, [$qid]);
                CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('unread_question', $uid)->delJudge($qid, 'unread_question');
                // 至时间排序列表 删除
                $this->listDataDel(0, [$qid], 0, 'time_sort');
            }
            CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $qid)->setCache($data);
            return true;
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
    }

    /**
     * 问答接单锁  最大重试次数 3次 重试等待时长 500毫秒
     * @param string $qid
     * @param int $maxRetryCount 最大重试次数
     * @param int $retryWaitTime 重试等待时长
     * @return bool
     * @throws \RedisException
     */
    public function astrReceivingLock(string $qid, int $maxRetryCount = 3, int $retryWaitTime = 500)
    {
        // 毫秒转微秒
        $cacheModel = CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('receiving_lock', $qid);
        $redis = $cacheModel->redisHandler;
        $retryWaitTime = $retryWaitTime * 1000;

        for ($i = 0; $i < $maxRetryCount; $i++)
        {
            $res = $redis->setnx($cacheModel->cacheKey['receiving_lock'], 1);
            if ($res)
            {
                $redis->expire($cacheModel->cacheKey['receiving_lock'], 20);  // 20秒过期时间
                return true;
            }
            usleep($retryWaitTime);
        }

        return false;
    }

    /**
     * 问答接单锁 删除
     * @param string $qid
     * @throws \Exception
     */
    public function astrReceivingUnLock(string $qid)
    {
        $cacheModel = CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('receiving_lock', $qid);
        $redis = $cacheModel->redisHandler;

        $redis->delete($cacheModel->cacheKey['receiving_lock']);
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            if ($ids)
            {
                $model = self::withTrashed()->where('id', 'in', $ids);
            } else
            {   // 我的问答列表
                $model = $this->where(['uid' => $type[0]]);
            }

            $data = $model
                ->order('create_time', 'DESC')
                ->column('uid,is_hide,status,question,question_type,gid,question_extend,is_synastry,read_num,is_read,discard_num,create_time,order_num,pay_time,extend,update_time,consult_num,receiving_num,good_amount,first_reply_time', 'id');
        }
        catch (\Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    /**
     * 获取问答首页 时间排序
     * @param int $page
     * @param int $limit
     * @return array|mixed
     * @throws \Exception
     */
    public function getQuestionTimeSortIds(int $page, int $limit = 10)
    {
        $resData = CacheManageZyhs::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setPage($page)
            ->setPageSize($limit)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc')
            {
                try
                {
                    $data = $this->where(['is_hide' => 0, 'first_reply_time' => ['>', 0]])->order('first_reply_time ' . $sortType)->column('first_reply_time', 'id');
                    $resData = [];
                    foreach ($data as $id => $firstReplyTime)
                    {
                        $resData[$id] = ['first_reply_time' => $firstReplyTime];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'first_reply_time', 0, 'time_sort');

        return $resData;
    }

    /**
     * 获取问答 用户未读ids
     * @param int $uid
     * @return array
     * @throws \Exception
     */
    public function getUserUnReadIds(int $uid): array
    {
        $resData = CacheManageZyhs::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('unread_question', $uid)
            ->setPage(-1)
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($uid)
            {
                try
                {
                    $data = $this->where(['uid' => $uid, 'is_read' => 0])->column('id');
                    $resData = [];
                    foreach ($data as $id)
                    {
                        $resData[$id] = ['id' => $id];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'id', 0, 'unread_question');

        return $resData['data'] ? array_keys($resData['data']) : [];
    }

    /**
     * 数据初始化
     * @param array $data
     * @return array
     */
    public function dataInit(array $data)
    {
        foreach ($data as $index => $itemData)
        {
            $data[$index] = arrayKeyData2int($itemData, ['is_hide', 'uid', 'status', 'question_type', 'gid', 'is_synastry', 'read_num', 'is_read', 'discard_num', 'create_time', 'pay_time', 'update_time', 'consult_num', 'receiving_num', 'good_amount', 'first_reply_time']);

            if (isset($itemData['question_extend']))
            {
                $data[$index]['question_extend'] = $itemData['question_extend'] ? json_decode($itemData['question_extend'], true) : [];
            }

            if (isset($itemData['extend']))
            {
                $data[$index]['extend'] = $itemData['extend'] ? json_decode($itemData['extend'], true) : [];
            }
        }

        return $data;
    }

    /**
     * 设置临时 问答数据
     * @param string $qidHash
     * @param string $questionStr
     * @return void
     */
    public function setTmpQuestionDataCache(string $qidHash, string $questionStr)
    {
        CacheZyhs::set('question_answer_tmp:' . $qidHash, $questionStr, 7200);
    }

    /**
     * 获取临时 问答数据
     * @param string $qidHash
     * @return array
     * @throws \Exception
     */
    public function getTmpQuestionDataCache(string $qidHash)
    {
        $dataStr = CacheZyhs::get('question_answer_tmp:' . $qidHash);

        if ($dataStr)
        {
            return json_decode($dataStr, true);
        } else
        {
            return [];
        }
    }

    /**
     * 删除临时 问答数据
     * @param string $qidHash
     * @throws \Exception
     */
    public function delTmpQuestionDataCache(string $qidHash)
    {
        CacheZyhs::rm('question_answer_tmp:' . $qidHash);
    }

    /**
     * 获取问题类型
     * @param int $gid
     * @return array
     * @throws ApiException
     */
    public function getQuestionType(int $gid)
    {
        $questionConfig = config('zyhs_question');
        $questionGoods = config('zyhsgoods.qa_goods');
        $addGids = array_values($questionConfig['add_question']);
        $lookGids = $questionConfig['look_gid'];
        $data = [];
        // 蹭看处理
        if ($gid === $lookGids)
        {
            $data['type'] = 1;
        } // 追问处理
        elseif (in_array($gid, $addGids, true))
        {
            $data['type'] = 2;
            switch ($questionGoods[$gid]['question_type'])
            {
                case 1:
                    $data['sec'] = 1;// 星盘
                    break;
                case 2:
                    $data['sec'] = 2;// 骰子
                    break;
                case 3:
                    $data['sec'] = 3;// 塔罗
                    break;
            }
        }// 问答处理
        elseif (isset($questionConfig['info'][$gid]))
        {
            $data['type'] = 3;
            switch ($questionGoods[$gid]['question_type'])
            {
                case 1:
                    $data['sec'] = 1;// 星盘
                    break;
                case 2:
                    $data['sec'] = 2;// 骰子
                    break;
                case 3:
                    $data['sec'] = 3;// 塔罗
                    break;
            }
        } else
        {
            Log::write('问题类型异常,商品ID：' . $gid, 'error', true);
            throw new ApiException('问题类型异常');
        }
        return $data;
    }

    /**
     * 获取本单问题的所有收益 和 用户本单实际支付总金额
     * @param array $questionInfo ['astr_id','task_id','good_amount',‘consult_num’,'gid']
     * @return array
     * @throws \Exception
     */
    public function getQuestionEarning(array $questionInfo)
    {
        $zyhsQuestionAnsertConfig = config('zyhs_question.add_question');
        $goodInfo = config('zyhsgoods.qa_goods');
        $proportionData = (new Zlcr3ConsultAccount())->getQuestionAnswerPercent();

        $oldPrice = (float)(sprintf('%.2f', (($questionInfo['good_amount'] / $questionInfo['consult_num']) / 10) * $proportionData['question']));
        $totalAmount = (float)(sprintf("%.2f", ($questionInfo['good_amount'] / $questionInfo['consult_num']) / 10));
        // 问题价格
        $questionPrice = (float)(sprintf("%.2f", $oldPrice));
        $addQuestionLists = (new ZyhsUserAddQuestion())->getQuestionAddQuestionInfo($questionInfo['task_id']);

        $addGid = $zyhsQuestionAnsertConfig[$questionInfo['gid']];
        // 计算咨询师 追问回复收益
        $addQuestionOldPrice = ($goodInfo[$addGid]['now_prize'] * $proportionData['add_question']) / 10;
        $addQuestionPrice = 0;
        foreach ($addQuestionLists as $addQuestionItem)
        {
            if ($addQuestionItem['status'] === 4)
            {   //  状态 1=>待支付  2=>待解答 3=>未支付已关闭 4=>已完成 5=>占星师申述已取消  6=>追问回复超时已取消
                $addQuestionPrice += $addQuestionOldPrice * $addQuestionItem['activity_discount'];
                if ($addQuestionItem['order_num'])
                {   // 准币单价 转换成 元
                    $totalAmount += ($goodInfo[$addGid]['now_prize'] / 10);
                }
            }
        }
        // 问题 + 追问 的总收益
        $totalPrice = (float)(sprintf("%.2f", $questionPrice + $addQuestionPrice));
        // 给收益扣税
        $earnings = Util::getAfterTaxAmount($totalPrice);

        return [
            'earning' => $earnings, // 单位 元
            'total_amount' => $totalAmount, // 单位 元
        ];
    }

    /**
     * 获取本单问题的所有收益包括追问待回答   仅进行中列表使用
     * @param array $questionInfo ['astr_id','task_id','good_amount',‘consult_num’,'gid']
     * @return float
     * @throws \Exception
     */
    public function getQuestionEarning2(array $questionInfo)
    {
        $zyhsQuestionAnsertConfig = config('zyhs_question.add_question');
        $goodInfo = config('zyhsgoods.qa_goods');
        $proportionData = (new Zlcr3ConsultAccount())->getQuestionAnswerPercent();

        $oldPrice = (float)(sprintf('%.2f', (($questionInfo['good_amount'] / $questionInfo['consult_num']) / 10) * $proportionData['question']));
        // 问题价格
        $questionPrice = (float)(sprintf("%.2f", $oldPrice));
        $addQuestionLists = (new ZyhsUserAddQuestion())->getQuestionAddQuestionInfo($questionInfo['task_id']);

        $addGid = $zyhsQuestionAnsertConfig[$questionInfo['gid']];
        // 计算咨询师 追问回复收益
        $addQuestionOldPrice = ($goodInfo[$addGid]['now_prize'] * $proportionData['add_question']) / 10;
        $addQuestionPrice = 0;
        foreach ($addQuestionLists as $addQuestionItem)
        {
            if (in_array($addQuestionItem['status'], [2, 4], true))
            {   //  状态 1=>待支付  2=>待解答 3=>未支付已关闭 4=>已完成 5=>占星师申述已取消  6=>追问回复超时已取消
                $addQuestionPrice += $addQuestionOldPrice * $addQuestionItem['activity_discount'];
            }
        }
        // 问题 + 追问 的总收益
        $totalPrice = (float)(sprintf("%.2f", $questionPrice + $addQuestionPrice));

        return Util::getAfterTaxAmount($totalPrice);
    }

    /**
     * 获取占星师 追问回复 预估收益 不参与活动折扣收益
     * @param int $gid 问答商品ID
     * @return float
     * @throws \Exception
     */
    public function getAddquestionEarning(int $gid)
    {
        $zyhsQuestionAnsertConfig = config('zyhs_question');
        $goodConfig = config('zyhsgoods.qa_goods');
        // 获取追问商品ID
        $addQuestionGid = $zyhsQuestionAnsertConfig['add_question'][$gid];
        // 获取追问价格
        $price = $goodConfig[$addQuestionGid]['now_prize']; // 单位 准币
        $proportionData = (new Zlcr3ConsultAccount())->getQuestionAnswerPercent();
        // 计算咨询师 追问回复收益   价格 * 分成比例
        $addQuestionOldPrice = $price * $proportionData['add_question'] / 10; // 转换成元

        return Util::getAfterTaxAmount(sprintf("%.2f", $addQuestionOldPrice));  // 预估收益 扣除营业税费及手续费
    }

    /**
     * 问答未接单退款
     * @param string $qid
     * @param string $reason
     * @return array
     * @throws \Exception
     */
    public function refund(string $qid, string $reason)
    {
        $question = $this->getInfoById($qid, ['consult_num', 'good_amount', 'order_num', 'receiving_num']);
        // 每人的单价
        $oneCoin = $question['good_amount'] / $question['consult_num'];
        // 未接单人数
        $refundPeopleNum = $question['consult_num'] - $question['receiving_num'];
        if ($refundPeopleNum > 0)
        {
            // 退款金额
            $refundPrice = $oneCoin * $refundPeopleNum / 10;
            (new ZyhsOrders())->refund($question['order_num'], $refundPrice, $reason);
            return [
                'status' => true,
                'refund_amount' => $refundPrice, // 单位 元
            ];
        }
        return [
            'status' => false,
            'refund_amount' => 0,
        ];
    }

    /**
     * 档案是否 已更新
     * @param array $oldRecode
     * @param array $nowRecode
     * @return bool
     */
    public function recodeModifyCheck(array $oldRecode, array $nowRecode): bool
    {
        $oldDataStr = "{$oldRecode['type']}:{$oldRecode['year']}:{$oldRecode['month']}:{$oldRecode['day']}:{$oldRecode['hour']}:{$oldRecode['minute']}:{$oldRecode['timezone']}:{$oldRecode['ew']}:{$oldRecode['long_deg']}:{$oldRecode['long_min']}:{$oldRecode['ns']}:{$oldRecode['lat_deg']}:{$oldRecode['lat_min']}:{$oldRecode['is_summer']}:{$oldRecode['live_country']}:{$oldRecode['live_province']}:{$oldRecode['live_city']}";
        $nowDataStr = "{$nowRecode['type']}:{$nowRecode['year']}:{$nowRecode['month']}:{$nowRecode['day']}:{$nowRecode['hour']}:{$nowRecode['minute']}:{$nowRecode['timezone']}:{$nowRecode['ew']}:{$nowRecode['long_deg']}:{$nowRecode['long_min']}:{$nowRecode['ns']}:{$nowRecode['lat_deg']}:{$nowRecode['lat_min']}:{$nowRecode['is_summer']}:{$nowRecode['live_country']}:{$nowRecode['live_province']}:{$nowRecode['live_city']}";

        return $oldDataStr !== $nowDataStr;
    }
}
